package com.wxyzz.satserver.article.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wxyzz.common.core.common.PageParam;
import com.wxyzz.common.core.entity.Article;
import com.wxyzz.common.core.entity.Comment;
import com.wxyzz.common.core.entity.User;
import com.wxyzz.common.core.exception.CustmerException;
import com.wxyzz.common.core.utils.DateUtils;
import com.wxyzz.common.core.utils.TokenUtils;
import com.wxyzz.common.core.utils.UserUtils;
import com.wxyzz.common.minio.utils.MinioUtil;
import com.wxyzz.common.redis.utils.RedisUtils;
import com.wxyzz.satserver.article.param.ArticleAddParam;
import com.wxyzz.satserver.article.dao.ArticleDao;
import com.wxyzz.satserver.article.param.CommentAddParam;
import com.wxyzz.satserver.article.param.UpdateEnshrineNumParam;
import com.wxyzz.satserver.article.param.UpdateLikeNumParam;
import com.wxyzz.satserver.article.service.ArticleService;
import com.wxyzz.satserver.article.vo.*;
import com.wxyzz.satserver.follow.service.FollowService;
import com.wxyzz.satserver.likeenshrine.service.LikeEnshrineService;
import com.wxyzz.satserver.user.service.UserService;
import jdk.nashorn.internal.parser.Token;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Resource
    private ArticleDao articleDao;

    @Resource
    private MinioUtil minioUtil;

    @Resource
    private FollowService followService;

    @Resource
    private LikeEnshrineService likeEnshrineService;

    @Resource
    private UserService userService;


/**
 * 发布文章的首页展示
 * @param param
 * @return
 */
    @Override
    public PageVO<ArticleVO> pageInfo(PageParam param) {

       //1、从数据库中查询Article信息并分页
        Page<Article> page = new Page<>(param.getPage(), param.getPageSize());
        page = articleDao.selectPage(page,
                new LambdaQueryWrapper<Article>()
                        .orderByDesc(Article::getCreateTime));

        List<Article> records = page.getRecords();

        System.out.println("首页文章的对象："+records);
        //通过stream流获取List<ArticleVO>对象
        List<ArticleVO> voList = records.stream().map(item -> {
            ArticleVO vo = new ArticleVO();
            User user = userService.selectById(item.getUidPublish());
            vo.setAvatar(user.getAvatar());
            vo.setUsername(user.getUsername());
            BeanUtils.copyProperties(item, vo);
            vo.setUid(item.getUidPublish());
            //vo.setLikeNum(0);
            //vo.setLikeFlag(0);
        //设置发布文章首页的封面，将article中的多个图片进行截取

            String imgPath = item.getImgPath();
            if (StringUtils.hasLength(imgPath)) {
                vo.setCoverImg(imgPath.split(",")[0]);
            }
            return vo;
        }).collect(Collectors.toList());

        PageVO<ArticleVO> pageVO = new PageVO<>();
        pageVO.setCurrentPage(page.getCurrent());
        pageVO.setTotal(page.getTotal());
        pageVO.setDataList(voList);
        return pageVO;
    }

/**
 * 点击封面，查看本篇文章的详细信息
 * @param aid
 * @return ShowArticleVO
 */

    @Override
    public ShowArticleVO findArticleById(Integer aid) {
        //先根据文章id获取文章的所有信息
        Article articleInfo = articleDao.selectById(aid);
        ShowArticleVO showArticleVO = new ShowArticleVO();
        //进行对象的复制，两个对象内部名字一样的字段才会复制
        BeanUtils.copyProperties(articleInfo,showArticleVO);
        //当前用户的id
        Integer uid = TokenUtils.getUidFromToken();
        // Integer uid = UserUtils.getUid();
        // 第一个参数：当前用户的id 第二个参数：发布文章博主的id
        Integer  concernFlag = followService.followStatus(uid,articleInfo.getUidPublish());
        showArticleVO.setConcernFlag(concernFlag);
        User user = userService.selectById(articleInfo.getUidPublish());
        showArticleVO.setAvatar(user.getAvatar());
        showArticleVO.setUsername(user.getUsername());
        return showArticleVO;
    }
/**
 * 发布文章把文章数据添加到数据库中
 * @param articleAddParam
 */
    @Override
    public void saveArticle(ArticleAddParam articleAddParam) {
        Integer uid = TokenUtils.getUidFromToken();
        //Integer uid = (Integer)RedisUtils.getValue("uid");
        Article article = new Article();
        BeanUtils.copyProperties(articleAddParam, article);
        // 将list集合中的图片以特定分隔符分割
        String imgPath = String.join(",", articleAddParam.getImgList());
        // imgPath = param.getImgList().stream().collect(Collectors.joining(","));
        article.setImgPath(imgPath);
        article.setUidPublish(uid);
        // 设置审核状态
        int insert = articleDao.insert(article);
        if (insert == 0){
            throw new CustmerException(500,"发布文章失败");
        }
    }

/**
 *  发布文章时，上传图片到 minio
 * @param file
 * @return
 */
    @Override
    public String uploadFile(MultipartFile file) {
       //获取源文件名
        String filename = file.getOriginalFilename();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        filename = uuid + filename.substring(filename.lastIndexOf("."));
        String path = null;
        try {
        //将图片文件上传到minio中
            path = minioUtil.upload(file.getInputStream(), filename, file.getContentType());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return path;
    }

/**
 * 依据热门话题label模糊查询相关热门文章
 * @param popularArticle
 * @return List<Article>
 */
    @Override
    public List<Article> findPopularArticle(String popularArticle) {
        List<Article> articles = articleDao.selectList(new LambdaQueryWrapper<Article>()
                .like(Article::getLabel, popularArticle));
        return articles;
    }

/**
 *展示文章的评论信息，根据文章id查询
 * @param aid
 * @return
 */
    @Override
    public List<CommentVO> findCommentInfo(Integer aid) {
        List<CommentVO> commentVOS = articleDao.selectCommentInfo(aid);
        return commentVOS;
    }

/**
 *添加文章的评论信息
 * @param param
 */
    @Override
    public void addCommentInfo(CommentAddParam param) {
        Integer uid = TokenUtils.getUidFromToken();
        param.setUidComment(uid);
        Integer insert = articleDao.insertCommentInfo(param);
        if (insert == 0){
            throw new CustmerException(500,"发布评论失败");
        }
    }

    /**
     * 查找热门话题文章
     * @return
     */
    @Override
    public List<Article> getHostTopicArticle() {
        List<Article> articles = articleDao.selectList(new LambdaQueryWrapper<Article>()
                .orderByDesc(Article::getLikeNum));
        String hostLabel = articles.get(0).getLabel();
        List<Article> hostLableArticles = articleDao.selectList(new LambdaQueryWrapper<Article>()
                .eq(Article::getLabel, hostLabel));
        // 需要查询当前登录用户是否关注过该文章
        hostLableArticles.forEach(item -> {

        });
        return hostLableArticles;
    }


    /**
     * 从redis中进行取数据，修改数据库中的点赞数
     */

    @Override
    public void  updateLikeNum(){
        //先获取存储在redis中点赞数的键
        String date = DateUtils.formatDate(new Date(), "yyyyMMdd");
        String redisKey = String.format("likeNum:%s", date);

        //根据键获取值，hash存储 文章id和点赞数
        Map<Object, Object> map = RedisUtils.hashGetAll(redisKey);
        List<UpdateLikeNumParam> list = new ArrayList<>();
        for(Object k : map.keySet()){
            UpdateLikeNumParam param = new UpdateLikeNumParam();
            Integer value = Integer.valueOf(map.get(k).toString());
            //判断每一个对象文章的点赞数是否有值
            if(!value.equals(0)){
                param.setAid(Integer.valueOf(k.toString()));
                param.setLikeNum(value);
                list.add(param);
            }
        }
        // 分批的批量更新，一次更新100条
        int count = 0;
        if (list.size() > 0) {
            List<UpdateLikeNumParam> temp = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                temp.add(list.get(i));
                count++;
                if (count == 100) {
                    // 批量更新
                    articleDao.updateLikeNumBatch(temp);
                    count = 0;
                    temp.clear();
                }
            }
            if (temp.size() > 0) {
                // 批量更新
                articleDao.updateLikeNumBatch(temp);
            }
        }
    }

    /**
     * 从redis中进行取数据，修改数据库中的收藏数
     */
    @Override
    public void  updateEnshrineNum(){
        //先获取存储在redis中收藏数的键
        String date = DateUtils.formatDate(new Date(), "yyyyMMdd");
        String redisKey = String.format("enshrineNum:%s", date);

        //根据键获取值，hash存储 文章id和收藏数
        Map<Object, Object> map = RedisUtils.hashGetAll(redisKey);
        List<UpdateEnshrineNumParam> list = new ArrayList<>();
        for(Object k : map.keySet()){
            UpdateEnshrineNumParam param = new UpdateEnshrineNumParam();
            Integer value = Integer.valueOf(map.get(k).toString());
            //判断每一个对象文章的收藏数是否有值
            if(!value.equals(0)){
                param.setAid(Integer.valueOf(k.toString()));
                param.setEnshrineNum(value);
                list.add(param);
            }
        }
        // 分批的批量更新，一次更新100条
        int count = 0;
        if (list.size() > 0) {
            List<UpdateEnshrineNumParam> temp = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                temp.add(list.get(i));
                count++;
                if (count == 100) {
                    // 批量更新
                    articleDao.updateEnshrineNumBatch(temp);
                    count = 0;
                    temp.clear();
                }
            }
            if (temp.size() > 0) {
                // 批量更新
                articleDao.updateEnshrineNumBatch(temp);
            }
        }
    }


/**
 * 查找热门话题文章
 * @return
 */
    @Override
    public String getHostTopic() {
        List<Article> articles = articleDao.selectList(new LambdaQueryWrapper<Article>()
                .orderByDesc(Article::getLikeNum));
        String hostLabel = articles.get(0).getLabel();
        return hostLabel;
    }


    // 查找热门话题文章
    @Override
    public List<HostLableArticle> getHostLableArticle(String hostLable) {
        // 查询该热门标题的文章
        List<Article> articles = articleDao.selectList(new LambdaQueryWrapper<Article>()
                .eq(Article::getLabel, hostLable));

        List<HostLableArticle> hostLableArticleList = articles.stream().map(item -> {
            HostLableArticle hostLableArticle = new HostLableArticle();
            hostLableArticle.setId(item.getId());

            // 获得第一张图片路径
            String[] split = item.getImgPath().split(",");

            hostLableArticle.setCoverImg(split[0]);
            hostLableArticle.setTitle(item.getTitle());
            hostLableArticle.setLikeNum(item.getLikeNum());

            Integer uid = UserUtils.getUid();

            hostLableArticle.setLikeStatus(likeEnshrineService.isLike(uid, item.getId(), 1));

            User user = userService.selectById(item.getUidPublish());
            hostLableArticle.setAvater(user.getAvatar());
            hostLableArticle.setNickname(user.getNickname());

            return hostLableArticle;

        }).collect(Collectors.toList());

        return hostLableArticleList;
    }

    // 文章详情
    @Override
    public ArticleDetail ArticleDetail(Integer id) {

        Article article = articleDao.selectById(id);

        ArticleDetail articleDetail = new ArticleDetail();

        articleDetail.setId(id);
        articleDetail.setUid(article.getUidPublish());
        articleDetail.setContent(article.getContent());

        String[] imgs = article.getImgPath().split(",");
        ArrayList<String> imgList = new ArrayList<>();
        for (String img : imgs) {
            imgList.add(img);
        }
        articleDetail.setImgPath(imgList);

        User user = userService.selectById(article.getUidPublish());
        articleDetail.setAvater(user.getAvatar());
        articleDetail.setNickname(user.getNickname());

        Integer uid = UserUtils.getUid();
        int likeStatus = likeEnshrineService.isLike(uid, article.getUidPublish(), 1);
        int collectStatus = likeEnshrineService.isCollect(uid, article.getUidPublish(), 2);
        articleDetail.setLikeStats(likeStatus);
        articleDetail.setCollectStatus(collectStatus);

        List<CommentVO> commentVOS = articleDao.selectCommentInfo(id);
        articleDetail.setCommentCount(commentVOS.size());

        int concernFlag = followService.followStatus(uid, article.getUidPublish());
        articleDetail.setConcernFlag(concernFlag);

        return articleDetail;
    }


    /**
     *查找目前登录用户个人的发布动态信息
     * @return
     */
    @Override
    public MyPageVO<ArticleVO> myPageInfo(PageParam param) {
        //1、从数据库中查询Article信息并分页
        Page<Article> page = new Page<>(param.getPage(), param.getPageSize());
        page = articleDao.selectPage(page,
                new LambdaQueryWrapper<Article>()
                        .orderByDesc(Article::getCreateTime));

        List<Article> records = page.getRecords();
        System.out.println("首页文章的对象："+records);

        //通过stream流获取List<ArticleVO>对象
        List<ArticleVO> voList = records.stream().map(item -> {
            ArticleVO vo = new ArticleVO();
            BeanUtils.copyProperties(item, vo);
            vo.setUid(item.getUidPublish());
            //vo.setLikeNum(0);
            //vo.setLikeFlag(0);
            //设置发布文章首页的封面，将article中的多个图片进行截取

            String imgPath = item.getImgPath();
            if (StringUtils.hasLength(imgPath)) {
                vo.setCoverImg(imgPath.split(",")[0]);
            }
            return vo;
        }).collect(Collectors.toList());

        MyPageVO<ArticleVO>  myPageVO = new MyPageVO<>();
        myPageVO.setCurrentPage(page.getCurrent());
        myPageVO.setTotal(page.getTotal());
        myPageVO.setDataList(voList);
        return myPageVO;
    }
}

